/**
 * 
 */
package database;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import database.util.FileUtil;

/**
 * @author sravanku
 *
 */
public class DataManager {
	
	static Map<String, DataFile> dataFiles = new HashMap<String, DataFile>();
	/**
	 * Creates and returns a new DataFile, throws IllegalArgumentException if fileName is already used.
	 * @param fileName -- fileName is used to identify the file if it was to be stored on disk and then retrieved from there.
	 * 						fileName must be unique.
	 * @param descriptor -- map of fields(columns names) and their maximum lengths
	 * @return <b>Datafile</b>
	 * @throws IllegalArgumentException
	 */
	// index_name -- table name
	public static Map<String, String> indexRefs = new HashMap<String, String>();
	
	public static DataFile createFile(String fileName, Map<String, Integer> descriptor, ArrayList<String> colOrder) throws IllegalArgumentException{

		 DataFile df=new DataFile(fileName,descriptor, colOrder);
	     File newfile = new File(fileName+".file");
	     
	     
	     
	     if(newfile.exists() || dataFiles.containsKey(fileName+".file"))
	       	 throw new IllegalArgumentException("fileName");	     
	     else
	     {
	    	 try {
	    		 newfile.createNewFile();
	    		 FileOutputStream filewrite=new FileOutputStream(newfile);
	    		 ObjectOutputStream oos = new ObjectOutputStream(filewrite);	    		 
	    		 oos.writeObject(df);
	    		 oos.close();
	    		 dataFiles.put(fileName, df);
	    	 } catch (IOException e) {
	    		 System.out.println("Error in creating new file");
	    	 }
	     }
	     return df;
	
	}

	
	public static DataFile createFile(String fileName, Map<String, Integer> descriptor) throws IllegalArgumentException{

		 DataFile df=new DataFile(fileName,descriptor);
	     File newfile = new File(fileName+".file");
	     
	     if(newfile.exists() || dataFiles.containsKey(fileName+".file"))
	       	 throw new IllegalArgumentException("fileName");	     
	     else
	     {
	    	 try {
	    		 newfile.createNewFile();
	    		 FileOutputStream filewrite=new FileOutputStream(newfile);
	    		 ObjectOutputStream oos = new ObjectOutputStream(filewrite);	    		 
	    		 oos.writeObject(df);	    		 
	    		 
	    	 } catch (IOException e) {
	    		 System.out.println("Error in creating new file");
	    	 }
	     }
	     return df;
	
	}

	/**
	 * restore the file contents from disk, returning that file, 
	 * if file of that name is already in memory or if file doesn't exist on disk throw IllegalArgumentException
	 * @param fileName
	 * @return <b>Datafile</b>
	 * @throws IllegalArgumentException
	 */
	public static DataFile restoreFile(String fileName) throws IllegalArgumentException{

		if(dataFiles.containsKey(fileName))
			throw new IllegalArgumentException("fileName");
		
		File f = new File(fileName+".file");
		if(!f.exists()){
			throw new IllegalArgumentException("fileName");
		}
		DataFile dataFile = null;
		try {
			FileInputStream fis = new FileInputStream(fileName+".file");
			ObjectInputStream in = new ObjectInputStream(fis);
			dataFile = (DataFile) in.readObject();
			in.close();
			
			return dataFile;
			
		} catch (IOException ex) {
			ex.printStackTrace();
		}catch (ClassNotFoundException ex){
			ex.printStackTrace();
		}
		return null;
	
	}
	
	/**
	 * print record contents in human-readable format, a record is represented as a Map that maps names of columns to data values. 
	 * Return as String what was printed.
	 * @param record Map<String, String> 
	 * @return <b>String</b>
	 */
	public static String print(Map<String, String> record){

		String returnstr=null;
		Iterator it=record.entrySet().iterator();
		while(it.hasNext())
		{
			Map.Entry keyValuepair = (Map.Entry)it.next();
			System.out.println(keyValuepair.getKey().toString()+": "+keyValuepair.getValue().toString());
			if(returnstr==null)
				returnstr=keyValuepair.getKey().toString()+": "+keyValuepair.getValue().toString()+"\n";
			else
				returnstr=returnstr+keyValuepair.getKey().toString()+": "+keyValuepair.getValue().toString()+"\n";
		}
			
        return returnstr;
	
	}
	
	/**
	 * Exit the system closing all files and saving all the information to disk
	 */
	public static void exit(){
		dataFiles.clear();
	}
	
	

	public static DataFile getFile(String fileName) throws IllegalArgumentException{

		if(dataFiles.containsKey(fileName))
			return dataFiles.get(fileName);
		else
		{
			File f = new File(fileName+".file");
			if(!f.exists()){
				throw new IllegalArgumentException("fileName");
			}
			DataFile dataFile = null;
			try {
				FileInputStream fis = new FileInputStream(fileName+".file");
				ObjectInputStream in = new ObjectInputStream(fis);
				dataFile = (DataFile) in.readObject();
				in.close();
				
				return dataFile;
				
			} catch (IOException ex) {
				ex.printStackTrace();
			}catch (ClassNotFoundException ex){
				ex.printStackTrace();
			}
		}
		return null;
	
	}
	
	public static void dropFile(String fileName) throws IllegalArgumentException{
		DataFile dftemp = null;
		if(dataFiles.containsKey(fileName))
			dftemp = dataFiles.get(fileName);
		else
		{
			// If file not loaded in memory
			File f = new File(fileName+".file");
			if(!f.exists()){
				throw new IllegalArgumentException("fileName");
			}
			DataFile dataFile = null;
			try {
				FileInputStream fis = new FileInputStream(fileName+".file");
				ObjectInputStream in = new ObjectInputStream(fis);
				dataFile = (DataFile) in.readObject();
				in.close();
				
		        dftemp = dataFile;
				
			} catch (IOException ex) {
				ex.printStackTrace();
			}catch (ClassNotFoundException ex){
				ex.printStackTrace();
			}
			
		}
		
		if(dftemp!=null)
		{
			dataFiles.remove(dftemp);
			dftemp.dropFile();
			new File(fileName+".file").delete();
		}
		
	}
	
	/*public static void dumpDataManager(){
		FileUtil.createFileFromObject("DataManager.data", );
	}*/
}
